package main

import (
	"fmt"
	"github.com.godemo/msgo"
	msLog "github.com.godemo/msgo/log"
	"github.com.godemo/msgo/mspool"
	"github.com.godemo/msgo/token"
	"log"
	"net/http"
	"sync"
	"time"
)

func Log(target msgo.HandlerFunc) msgo.HandlerFunc {
	return func(ctx *msgo.Context) {
		queryParams := ctx.R.URL.Query()
		if len(queryParams) > 0 {
			for key, values := range queryParams {
				fmt.Printf("key:%s  value:%s \n", key, values)
			}
		} else {
			fmt.Println("该请求没有参数")

		}

		target(ctx)
		fmt.Println("结果打印:" + ctx.R.Method)
	}
}

type User struct {
	Name  string   `json:"name" xml:"name" msgo:"required"`
	Age   int      `json:"age" xml:"age" validate:"required,max=50,min=18"`
	Addr  []string `json:"addr" xml:"addr"`
	Email string   `json:"email" xml:"email" msgo:"required"`
}

func main() {
	user := &User{
		Name: "ddd",
		Age:  18,
	}
	engine := msgo.Default()
	engine.RegisterErrorHandler(func(err error) (int, any) {
		switch e := err.(type) {
		case *BlogError:
			return http.StatusOK, e.Response()
		default:
			return http.StatusInternalServerError, "500 error"
		}
	})
	fmt.Println(msgo.BasicAuth("lsx", "123456"))
	auth := &msgo.Accounts{
		Users: make(map[string]string),
	}
	auth.Users["lsx"] = "123456"
	msToken := &token.JwtHandler{Key: []byte("123456"), Alg: "HS256"}
	//engine.Use(auth.BasicAuth)
	engine.Use(msToken.AuthInterceptor)
	g := engine.Group("user")
	g.PreHandle(func(target msgo.HandlerFunc) msgo.HandlerFunc {
		return func(ctx *msgo.Context) {
			fmt.Println("pre handle 111")
			target(ctx)
			fmt.Println("post handle 111")
		}
	})
	a := func(target msgo.HandlerFunc) msgo.HandlerFunc {
		return func(ctx *msgo.Context) {
			fmt.Println("pre handle 2222")
			target(ctx)
			fmt.Println("post handle 222")
		}
	}
	g.PreHandle(a)
	g.Get("/hello", func(ctx *msgo.Context) {
		fmt.Println("hello handler done")
		fmt.Fprintln(ctx.W, "hello mszlu.com+++ get")
	}, Log)
	g.Put("/hello", func(ctx *msgo.Context) {
		fmt.Fprintln(ctx.W, "hello mszlu.com+++ put")
	})
	g.Get("/login", func(ctx *msgo.Context) {
		jwt := &token.JwtHandler{}
		jwt.Key = []byte("123456")
		jwt.SendCookie = true
		jwt.TimeOut = 10 * time.Minute
		jwt.RefreshTimeOut = 20 * time.Minute
		jwt.Authenticator = func(ctx *msgo.Context) (map[string]any, error) {
			data := make(map[string]any)
			data["userId"] = 1
			return data, nil
		}
		msToken, err := jwt.LoginHandler(ctx)
		if err != nil {
			log.Println(err)
			ctx.Json(http.StatusOK, err.Error())
			return
		}
		ctx.Json(http.StatusOK, msToken)
	})
	g.Get("/refreshToken", func(ctx *msgo.Context) {
		jwt := &token.JwtHandler{Alg: "HS256"}
		jwt.Key = []byte("123456")
		jwt.SendCookie = true
		jwt.TimeOut = 10 * time.Minute
		jwt.RefreshTimeOut = 20 * time.Minute
		jwt.RefreshKey = "blog_refresh_token"
		ctx.Set(jwt.RefreshKey, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NjA2OTEyMDMsImlhdCI6MTc2MDY5MDAwMywidXNlcklkIjoxfQ.psLVFk_bmgDxHCwCwPO4IbQvBetLWsERN6PkYJRmBK8")
		refreshToken, err := jwt.RefreshHandler(ctx)
		if err != nil {
			log.Println(err)
			_ = ctx.Json(http.StatusOK, err.Error())
			return
		}
		_ = ctx.Json(http.StatusOK, refreshToken)
	})
	g2 := engine.Group("index")
	g2.Post("/test/ddd/ccc", func(ctx *msgo.Context) {
		fmt.Fprintln(ctx.W, "hello mszlu.com2222")
	})
	g2.Get("/templateGlob", func(ctx *msgo.Context) {
		err := ctx.HTMLTemplateGolb("login.html", user, "tpl/*.html")
		if err != nil {
			log.Println(err)
		}
	})
	g2.Get("/template", func(ctx *msgo.Context) {
		err := ctx.Template("login.html", user)
		if err != nil {
			log.Println(err)
		}
	})

	engine.Logger.Level = msLog.LevelInfo
	//engine.Logger.Formatter = &msLog.TextFormatter{}
	//engine.Logger.Formatter = &msLog.JsonFormatter{TimeDisplay: true}
	//logger.Outs = append(logger.Outs, msLog.FileWriter("./log/log.log"))
	engine.Logger.SetLogPath("./log")
	g2.Get("/json", func(ctx *msgo.Context) {
		err := ctx.Json(http.StatusOK, user)
		ctx.Logger.Debug("我是debug日志")
		ctx.Logger.WithFiled(msLog.Fields{"name": "ddd", "age": 18}).Info("我是info日志")
		ctx.Logger.Error("我是error日志")
		if err != nil {
			log.Println(err)
		}
	})
	g2.Get("/xml", func(ctx *msgo.Context) {
		err := ctx.Xml(http.StatusOK, user)
		if err != nil {
			log.Println(err)
		}
	})
	g2.Get("/file", func(ctx *msgo.Context) {
		ctx.FileAttachment("tpl/test.xlsx", "aaaa.xlsx")

	})
	g2.Get("/fileFormFs", func(ctx *msgo.Context) {
		ctx.FileFromFS("test.xlsx", http.Dir("tpl"))

	})
	g2.Get("/toRedirect", func(ctx *msgo.Context) {
		ctx.Redirect(http.StatusFound, "/user/hello")
	})
	g2.Get("/string", func(ctx *msgo.Context) {
		ctx.String(http.StatusOK, "%s 是由 %s 制作 \n", "goweb框架", "go微服务框架")

	})
	g3 := engine.Group("any")
	g3.Any("/go", func(ctx *msgo.Context) {
		fmt.Fprintln(ctx.W, "hello mszlu.com33333")
	})
	g3.Get("/add", func(ctx *msgo.Context) {
		//id := ctx.GetQuery("id")
		//fmt.Printf("id:%s", id)
		id, ok := ctx.GetQueryArray("id")
		log.Printf("id:%v,ok:%v \n", id, ok)
	})
	g3.Get("/queryMap", func(ctx *msgo.Context) {
		m, _ := ctx.GetQueryMap("user")
		ctx.Json(http.StatusOK, m)
	})
	g3.Get("/formPost", func(ctx *msgo.Context) {
		m, _ := ctx.GetPostFormMap("user")
		ctx.Json(http.StatusOK, m)
	})
	g3.Post("/file", func(ctx *msgo.Context) {
		file, err := ctx.FormFile("file")
		if err != nil {
			log.Println(err)
		}
		err = ctx.SaveUploadedFile(file, "./upload/"+file.Filename)
		if err != nil {
			log.Println(err)
		}

	})
	g3.Post("/jsonParam", func(ctx *msgo.Context) {
		user := make([]User, 0)
		ctx.DisallowUnknownFields = true
		ctx.IsValidate = true
		_ = ctx.BindJson(&user)
		errLogin := login()
		ctx.HandlerWithError(http.StatusOK, user, errLogin)
	})
	g3.Post("/xmlParam", func(ctx *msgo.Context) {
		user := &User{}
		err := ctx.BindXml(user)
		if err == nil {
			ctx.Json(http.StatusOK, user)
		} else {
			log.Println(err)
		}
	})
	p, _ := mspool.NewPool(1)
	g3.Post("/pool", func(ctx *msgo.Context) {
		currentTime := time.Now().UnixMilli()
		var wg sync.WaitGroup
		wg.Add(5)
		p.Submit(func() {
			wg.Done()
			fmt.Println("111111111111")
			panic("这是1111的panic")
			time.Sleep(3 * time.Second)

		})
		p.Submit(func() {
			fmt.Println("222222222")
			time.Sleep(3 * time.Second)
			wg.Done()
		})
		p.Submit(func() {
			fmt.Println("333333333")
			time.Sleep(3 * time.Second)
			wg.Done()
		})
		p.Submit(func() {
			fmt.Println("4444444444")
			time.Sleep(3 * time.Second)
			wg.Done()
		})
		p.Submit(func() {
			fmt.Println("5555555555")
			time.Sleep(3 * time.Second)
			wg.Done()
		})
		wg.Wait()
		fmt.Printf("耗时:%v \n", time.Now().UnixMilli()-currentTime)
		ctx.Json(http.StatusOK, "success")
	})

	engine.LoadTemplate("tpl/*.html")
	engine.RunTLS(":8080", "key/server.pem", "key/server.key")
	//engine.Run()
}

func login() *BlogError {
	return &BlogError{
		Success: false,
		Code:    -999,
		Data:    nil,
		Msg:     "账号密码错误",
	}
}

type BlogError struct {
	Success bool
	Code    int64
	Data    any
	Msg     string
}

type BlogNoDataError struct {
	Success bool
	Code    int64
	Msg     string
}

func (b *BlogError) Error() string {
	return b.Msg
}

func (b *BlogError) Fail(code int64, msg string) {
	b.Success = false
	b.Code = code
	b.Msg = msg
}

func (b *BlogError) Response() any {
	if b.Data == nil {
		return &BlogNoDataError{
			Success: b.Success,
			Code:    b.Code,
			Msg:     b.Msg,
		}
	}
	return b
}
